<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8" />
<!--[if lt IE 9]>
  <script src="https://oss.maxcdn.com/libs/html5shiv/3.7.0/html5shiv.js"></script>
<![endif]-->
<title>VIM 中文帮助: 定义用户函数</title>
<link rel="stylesheet" href="vim-stylesheet.css" type="text/css" />
<link rel="canonical" href="https://yianwillis.github.io/vimcdoc/doc/userfunc.html" />
<script type="text/javascript" src="vimcdoc.js"></script>
<meta name="viewport" content="width=device-width, initial-scale=1" />
</head>
<body>
<nav id=banner>
<form action=tags.html target="tag_iframe">
  <input type="text" name="tag" id="tag" placeholder="标签搜索">
</form>
<iframe name="tag_iframe" src=""></iframe>
<a href="help.html">帮助总览</a> &middot;
<hr/>
<a href="quickref.html">快速参考</a> &middot;
<a href="index.html">命令索引</a> &middot;
<a href="eval.html#functions">函数列表</a> &middot;
<a href="quickref.html#option-list">选项列表</a> &middot;
<hr/>
<a href="usr_toc.html">用户手册</a> &middot;
<a href="help.html#reference_toc">参考手册</a> &middot;
</nav>

<header>
<h2>userfunc</h2>
</header>
<article id=outer>
<section class=inner>
<b class="vimtag"> <a name="userfunc.txt">userfunc.txt</a> </b>      适用于 Vim 9.0 版本。       最近更新: 2023年2月


                  <code class="vim">VIM 参考手册    by Bram Moolenaar</code>
                                <code class="vim">译者</code>: Willis


定义和使用函数。

用户手册的  <a href="usr_41.html#41.7">41.7</a>  一节有相关介绍。

1. 定义函数                              <a href="userfunc.html#define-function">define-function</a> 
2. 调用函数                              <a href="userfunc.html#:call">:call</a> 
3. 函数清理                              <a href="userfunc.html#:defer">:defer</a> 
4. 自动载入函数                          <a href="userfunc.html#autoload-functions">autoload-functions</a> 

</section><hr class="doubleline" /><section class=inner>
<h4></h4><code class="section">1. 定义函数 </code>
                                                <b class="vimtag"> <a name="define-function">define-function</a> </b>
可以定义新的函数。调用的方式就像内建函数一样。函数执行一系列 Ex 命令。普通模式
下的命令可以用  <a href="various.html#:normal">:normal</a>  命令执行。

函数名须以大写字母开始，以免和内建函数引起混淆。要避免在不同脚本使用相同的名
字，请使其局部于脚本。如果必须使用全局函数，避免显见的或者过短的名字。一个好习
惯是使用脚本名字作为函数名字的开头，比如 "HTMLcolor()"。

老式脚本里也可以使用花括号，见  <a href="eval.html#curly-braces-names">curly-braces-names</a> 。

 <a href="userfunc.html#autoload">autoload</a>  机制可用于在调用时才提供函数的定义。

                                                        <b class="vimtag"> <a name="local-function">local-function</a> </b>
局部于老式脚本的函数必须以 "s:" 开始。局部于脚本的函数只能在同一脚本和脚本中定
义的函数、用户命令和自动命令里调用。也可以在脚本定义的映射里调用该函数，但必须
使用  <a href="map.html#%3CSID%3E">&lt;SID&gt;</a>  而不是 "s:"，如果映射会在脚本之外被扩展的话。
只有局部于脚本的函数，没有局部于缓冲区或局部于窗口的函数。

 <a href="vim9.html#Vim9">Vim9</a>  的脚本函数缺省局部于脚本，要定义全局函数需要 "g:" 前缀。

                                <b class="vimtag"> <a name=":fu">:fu</a> </b> <b class="vimtag"> <a name=":function">:function</a> </b> <b class="vimtag"> <a name="E128">E128</a> </b> <b class="vimtag"> <a name="E129">E129</a> </b> <b class="vimtag"> <a name="E123">E123</a> </b> <b class="vimtag"> <a name="E454">E454</a> </b>
:fu[nction]             列出所有函数和它们的参数。

:fu[nction] <code class="special">{name}</code>      列出 <code class="special">{name}</code> 命名的函数。
                        <code class="special">{name}</code> 也可以是  <a href="eval.html#Funcref">Funcref</a>  类型的  <a href="eval.html#Dictionary">Dictionary</a>  项目: 
<code class="example">                                :function dict.init</code>
<code class="example"></code>
:fu[nction] /<code class="special">{pattern}</code>  列出名字匹配 <code class="special">{pattern}</code> 的函数。
                        列出所有以 "File" 结束的函数的例子: 
<code class="example">                                :function /File$</code>

                                                        <b class="vimtag"> <a name=":function-verbose">:function-verbose</a> </b>
如果 <a href="options.html#'verbose'">'verbose'</a> 非零，列出函数的同时也显示它上次定义的位置。例如: 
<code class="example"></code>
<code class="example">    :verbose function SetFileTypeSH</code>
<code class="example">        function SetFileTypeSH(name)</code>
<code class="example">            Last set from /usr/share/vim/vim-7.0/filetype.vim</code>

 <a href="various.html#:verbose-cmd">:verbose-cmd</a>  有更多信息。

                                                <b class="vimtag"> <a name="E124">E124</a> </b> <b class="vimtag"> <a name="E125">E125</a> </b> <b class="vimtag"> <a name="E853">E853</a> </b> <b class="vimtag"> <a name="E884">E884</a> </b>
:fu[nction][!] <code class="special">{name}</code>(<code class="special">[arguments]</code>) <code class="special">[range]</code> <code class="special">[abort]</code> <code class="special">[dict]</code> <code class="special">[closure]</code>
                        定义 <code class="special">{name}</code> 命名的新函数。函数体在之后的行给出，直到匹
                        配的  <a href="userfunc.html#:endfunction">:endfunction</a>  为止。

                                                                <b class="vimtag"> <a name="E1267">E1267</a> </b>
                        名字必须由字母数字和 '_' 字符组成，而且必须以大写字母
                        或者 "s:" 开头 (见上)。<code class="note">注意</code> "b:" 或 "g:" 是不允许的。(
                        从补丁 7.4.260 开始，如果函数名中有冒号，给出 E884，
                        如 "foo:bar()"。此补丁之前不报错)。

                        <code class="special">{name}</code> 也可以是  <a href="eval.html#Funcref">Funcref</a>  类型的  <a href="eval.html#Dictionary">Dictionary</a>  项目: 
<code class="example">                                :function dict.init(arg)</code>
                        "dict" 必须是一个已经存在的字典。如果还不存在，项目
                        "init" 被加入此字典。否则必须提供 [!] 以覆盖已经存在的
                        函数。返回指向一个编号函数的  <a href="eval.html#Funcref">Funcref</a> 。该函数只能通过
                         <a href="eval.html#Funcref">Funcref</a>  引用，没有引用指向它时，该函数会被删除。
                                                                <b class="vimtag"> <a name="E127">E127</a> </b> <b class="vimtag"> <a name="E122">E122</a> </b>
                        如果同名的函数已经存在而且没有使用 [!]，给出错误信息。
                        有一个例外: 再次执行脚本时，该脚本中之前定义过的函数会
                        被悄然替代。
                        如果给出 [!]，已有的函数被悄然替代。如果该函数正在执行
                        期间除外。此时，这是一个错误。
                        <code class="note">备注</code>: 小心使用 !。如果不小心，可能会意外地替代已有的函
                        数。这很难调试。
                        <code class="note">备注</code>: Vim9 脚本里局部于脚本的函数不能被删除或重定义。

                        <code class="special">{arguments}</code> 参见  <a href="userfunc.html#function-argument">function-argument</a> 。

                                        <b class="vimtag"> <a name=":func-range">:func-range</a> </b> <b class="vimtag"> <a name="a:firstline">a:firstline</a> </b> <b class="vimtag"> <a name="a:lastline">a:lastline</a> </b>
                        如果给出 <code class="special">[range]</code> 参数，则该函数自己能理解并处理行范
                        围。该范围通过 "a:firstline" 和 "a:lastline" 定义。如
                        果没有 <code class="special">[range]</code>，":<code class="special">{range}</code>call" 会在该范围的每一行分别
                        执行该函数，每次光标都定位在处理行的行首。见
                         <a href="userfunc.html#function-range-example">function-range-example</a> 。
                        就像所有的 Ex 命令一样，光标仍然会被移动到范围的首行。
                                                                <b class="vimtag"> <a name=":func-abort">:func-abort</a> </b>
                        如果给出 <code class="special">[abort]</code> 参数，该函数在遇到错误时立即中止。
                                                                <b class="vimtag"> <a name=":func-dict">:func-dict</a> </b>
                        如果给出 <code class="special">[dict]</code> 参数，该函数必须通过  <a href="eval.html#Dictionary">Dictionary</a>  的项
                        目才能调用。局部变量 "self" 这时设为该字典。见
                         <a href="eval.html#Dictionary-function">Dictionary-function</a> 。
                                                <b class="vimtag"> <a name=":func-closure">:func-closure</a> </b> <b class="vimtag"> <a name="E932">E932</a> </b>
                        加入 <code class="special">[closure]</code> 参数时，函数可以访问外部作用域的变量和
                        参数。通常这被称为闭包。此例中 Bar() 使用 Foo() 作用
                        域的 "x"。即使 Foo() 返回后仍被引用: 
<code class="example">                                :function! Foo()</code>
<code class="example">                                :  let x = 0</code>
<code class="example">                                :  function! Bar() closure</code>
<code class="example">                                :    let x += 1</code>
<code class="example">                                :    return x</code>
<code class="example">                                :  endfunction</code>
<code class="example">                                :  return funcref('Bar')</code>
<code class="example">                                :endfunction</code>
<code class="example"></code>
<code class="example">                                :let F = Foo()</code>
<code class="example">                                :echo F()</code>
                                1 
<code class="example">                                :echo F()</code>
                                2 
<code class="example">                                :echo F()</code>
                                3


                                                <b class="vimtag"> <a name="function-search-undo">function-search-undo</a> </b>
                        最近使用的搜索模式和重做命令 "." 不会受到函数的影响。
                        这也意味着  <a href="pattern.html#:nohlsearch">:nohlsearch</a>  的效果在函数返回时会被撤销。

                        <b class="vimtag"> <a name=":endf">:endf</a> </b> <b class="vimtag"> <a name=":endfunction">:endfunction</a> </b> <b class="vimtag"> <a name="E126">E126</a> </b> <b class="vimtag"> <a name="E193">E193</a> </b> <b class="vimtag"> <a name="W22">W22</a> </b> <b class="vimtag"> <a name="E1151">E1151</a> </b>
:endf[unction]          结束函数定义。最好单起一行，没有 <code class="special">[argument]</code>。

                        <code class="special">[argument]</code> 可以是:
                                | 命令          下面执行的命令
                                \n 命令         下面执行的命令
                                " 注释          总是忽略
                                其它            忽略，如果 <a href="options.html#'verbose'">'verbose'</a> 非零给出
                                                <code class="note">警告</code>
                        对后续命令的支持是 Vim 8.0.0654 加入的，之前任何参数都
                        被悄悄地忽略。

                        要在  <a href="eval.html#:execute">:execute</a>  命令里定义函数，用换行符而不是
                         <a href="cmdline.html#:bar">:bar</a> : 
<code class="example">                                :exe "func Foo()\necho 'foo'\nendfunc"</code>

                                <b class="vimtag"> <a name=":delf">:delf</a> </b> <b class="vimtag"> <a name=":delfunction">:delfunction</a> </b> <b class="vimtag"> <a name="E131">E131</a> </b> <b class="vimtag"> <a name="E933">E933</a> </b> <b class="vimtag"> <a name="E1084">E1084</a> </b>
:delf[unction][!] <code class="special">{name}</code>
                        删除 <code class="special">{name}</code> 命名的函数。
                        <code class="special">{name}</code> 也可以是  <a href="eval.html#Funcref">Funcref</a>  类型的  <a href="eval.html#Dictionary">Dictionary</a>  项目: 
<code class="example">                                :delfunc dict.init</code>
                        会删除 "dict" 的 "init" 项目。如果没有更多指向它的引
                        用，该函数被删除。
                        用了 ! 后，即使函数不存在也不报错。
                                                <b class="vimtag"> <a name=":retu">:retu</a> </b> <b class="vimtag"> <a name=":return">:return</a> </b> <b class="vimtag"> <a name="E133">E133</a> </b>
:retu[rn] <code class="special">[expr]</code>        从函数返回。如果给出 "[expr]"，计算该表达式的结果成为
                        函数的返回值。如果没有给出 "[expr]"，返回 0。
                        如果函数退出时没有显式的调用 ":return"，返回 0。
                        :def 函数里，如果  <a href="userfunc.html#:return">:return</a>  之后有不可到达的行，给出
                        <b class="vimtag"> <a name="E1095">E1095</a> </b> 。
                        老式脚本里没有不可到达行的检查，因而，如果有命令在
                        ":return" 之后，不会给出<code class="note">警告</code>。也不检查后续行是否包含合
                        法的命令。这样可能会察觉不到忘记了续行的反斜杠: 
<code class="example">                                return 'some text'</code>
<code class="example">                                       .. ' some more text'</code>
                        会高兴地返回 "some text" 而不报错。这本来应该是: 
<code class="example">                                return 'some text'</code>
<code class="example">                                       \ .. ' some more text'</code>

                        如果 ":return" 在  <a href="eval.html#:try">:try</a>  之后使用但在匹配的  <a href="eval.html#:finally">:finally</a> 
                        (如果有的话) 之前的话，":finally" 之后直到匹配的
                         <a href="eval.html#:endtry">:endtry</a>  的命令会先执行。该过程反复应用于所有函数内的
                        嵌套 ":try" 块。在最外层 ":endtry" 结束之后才真正返
                        回。


                                                <b class="vimtag"> <a name="function-argument">function-argument</a> </b> <b class="vimtag"> <a name="a:var">a:var</a> </b>
参数的定义只要给出它的名字。在函数里，可以使用 "a:name" 来访问 ("a:" 代表参数
(argument))。
                                        <b class="vimtag"> <a name="a:0">a:0</a> </b> <b class="vimtag"> <a name="a:1">a:1</a> </b> <b class="vimtag"> <a name="a:000">a:000</a> </b> <b class="vimtag"> <a name="E740">E740</a> </b> <b class="vimtag"> <a name="...">...</a> </b>
可以给出不超过 20 个参数，以逗号分隔。最后，可以给出参数 "..."，意味着可以有更
多的参数。在函数里，可以通过 "a:1"、"a:2" 等等访问它们。"a:0" 设为这些附加参数
的数目 (可以为 0)。"a:000" 设为包含这些参数的  <a href="eval.html#List">List</a> 。<code class="note">注意</code> "a:1" 等同于
"a:000[0]"。
                                                        <b class="vimtag"> <a name="E742">E742</a> </b> <b class="vimtag"> <a name="E1090">E1090</a> </b>
a: 作用域和其中的变量不能修改，它们是固定的。不过，如果使用了复合类型，例如
 <a href="eval.html#List">List</a>  或  <a href="eval.html#Dictionary">Dictionary</a> ，可以改变它们的内容。这样就可以传递给函数一个  <a href="eval.html#List">List</a> ，
让该函数在里面增加项目。如果要确保函数不能修改  <a href="eval.html#List">List</a>  或  <a href="eval.html#Dictionary">Dictionary</a> ，用
 <a href="eval.html#:lockvar">:lockvar</a> 。

可以定义没有参数的函数。但你这时仍然需要提供 ()。

可以在函数体里定义别的函数。

                                                <b class="vimtag"> <a name="optional-function-argument">optional-function-argument</a> </b>
可以提供位置命名参数的缺省值。这使得函数调用时它们成为可选参数。位置参数如果在
调用时不指定，则使用缺省表达式来初始化。
只用于  <a href="userfunc.html#:function">:function</a>  或  <a href="vim9.html#:def">:def</a>  声明的函数，而不适用于匿名表达式  <a href="eval.html#expr-lambda">expr-lambda</a> 。

示例: 
<code class="example">  function Something(key, value = 10)</code>
<code class="example">     echo a:key .. ": " .. a:value</code>
<code class="example">  endfunction</code>
<code class="example">  call Something('empty')       "empty: 10"</code>
<code class="example">  call Something('key', 20)     "key: 20"</code>
<code class="example"></code>
参数的缺省表达式在函数调用时而非定义时进行计算。这样就可用函数定义时非法的表达
式。该表达式也只在调用中未指定参数时才进行计算。

                                                <b class="vimtag"> <a name="none-function_argument">none-function_argument</a> </b>
 <a href="eval.html#v:none">v:none</a>  可用来指示参数使用缺省表达式。<code class="note">注意</code> 这意味着如果有缺省表达式，参数不接
受 v:none 作为其正常值传递。

示例: 
<code class="example">  function Something(a = 10, b = 20, c = 30)</code>
<code class="example">  endfunction</code>
<code class="example">  call Something(1, v:none, 3)      " b = 20</code>

                                                                <b class="vimtag"> <a name="E989">E989</a> </b>
带缺省表达式的可选参数必须在任何必选参数之后出现。"..." 可在所有可选命名参数之
后使用。

出现在后面的参数的缺省可引用在它之前的参数，反之不可以。就像所有参数一样，必须
使用 "a:" 前缀。

合法的例子: 
<code class="example">  :function Okay(mandatory, optional = a:mandatory)</code>
<code class="example">  :endfunction</code>
 <code class="emphasis">不</code> 合法的例子: 
<code class="example">  :function NoGood(first = a:second, second = 10)</code>
<code class="example">  :endfunction</code>

如果不使用 "..."，实际给出的参数数目必须至少等于必选参数的数目。如果使用
"..."，参数的数目可以多于必选和可选参数的总数。

                                                        <b class="vimtag"> <a name="local-variables">local-variables</a> </b>
在函数里，可以使用局部变量。它们在函数返回时就会消失。全局变量的访问需要通过
"g:"。
函数内可以不用前缀进行访问局部变量。但如果想要，也可用 "l:" 前缀。对某些保留名
字而言，这是必须的。

例如: 
<code class="example">  :function Table(title, ...)</code>
<code class="example">  :  echohl Title</code>
<code class="example">  :  echo a:title</code>
<code class="example">  :  echohl None</code>
<code class="example">  :  echo a:0 .. " items:"</code>
<code class="example">  :  for s in a:000</code>
<code class="example">  :    echon ' ' .. s</code>
<code class="example">  :  endfor</code>
<code class="example">  :endfunction</code>
<code class="example"></code>
该函数这时可以这样调用: 
<code class="example">  call Table("Table", "line1", "line2")</code>
<code class="example">  call Table("Empty Table")</code>
<code class="example"></code>
要返回多于一个值，返回一个  <a href="eval.html#List">List</a> : 
<code class="example">  :function Compute(n1, n2)</code>
<code class="example">  :  if a:n2 == 0</code>
<code class="example">  :    return ["fail", 0]</code>
<code class="example">  :  endif</code>
<code class="example">  :  return ["ok", a:n1 / a:n2]</code>
<code class="example">  :endfunction</code>
<code class="example"></code>
该函数这时可以这样调用: 
<code class="example">  :let [success, div] = Compute(102, 6)</code>
<code class="example">  :if success == "ok"</code>
<code class="example">  :  echo div</code>
<code class="example">  :endif</code>

</section><hr class="doubleline" /><section class=inner>
<h4></h4><code class="section">2. 调用函数 </code>
                                                <b class="vimtag"> <a name=":cal">:cal</a> </b> <b class="vimtag"> <a name=":call">:call</a> </b> <b class="vimtag"> <a name="E107">E107</a> </b>
:<code class="special">[range]</code>cal[l] <code class="special">{name}</code>(<code class="special">[arguments]</code>)
                调用函数。函数名和参数通过  <a href="userfunc.html#:function">:function</a>  指定。可以使用不超过 20
                个参数。忽略返回值。
                 <a href="vim9.html#Vim9">Vim9</a>  脚本的  <a href="userfunc.html#:call">:call</a>  的使用是可选的，因此以下两行是等价的: 
<code class="example">                        call SomeFunc(arg)</code>
<code class="example">                        SomeFunc(arg)</code>
                如果没有给出范围而函数又接受范围，该函数被调用一次。如果给出范
                围，光标在执行函数前定位在该范围的第一行的开始。
                如果给出范围但函数自己不能处理之，该函数在范围里的每一行分别执
                行。光标定位在每个处理行的第一列。光标留在最后一行 (但可能被最
                后一个函数调用移动)。每一行上，参数被重新计算。所以这是可以的:
                                                <b class="vimtag"> <a name="function-range-example">function-range-example</a> </b>  
<code class="example">        :function Mynumber(arg)</code>
<code class="example">        :  echo line(".") .. " " .. a:arg</code>
<code class="example">        :endfunction</code>
<code class="example">        :1,5call Mynumber(getline("."))</code>

                "a:firstline" 和 "a:lastline" 总是有定义的。它们可以用来在范围
                的开始或结束处进行一些不同的处理。

                能处理范围本身的函数示例: 
<code class="example"></code>
<code class="example">        :function Cont() range</code>
<code class="example">        :  execute (a:firstline + 1) .. "," .. a:lastline .. 's/^/\t\\ '</code>
<code class="example">        :endfunction</code>
<code class="example">        :4,8call Cont()</code>

                该函数在范围里的每行开头插入续行符 "\"，除了第一行以外。

                如果函数返回复合值，该值可被进一步解除参照 (<code class="vim">译者注</code>: 调用其上的
                方法)，但该范围不能被继续使用。例如: 
<code class="example">        :4,8call GetDict().method()</code>
                这里 GetDict() 得到范围值，method() 不会。

                                                                <b class="vimtag"> <a name="E117">E117</a> </b>
找不到函数时，会给出 "E117: Unknown function" 错误。如果函数使用了自动载入路径
或自动载入导入语句并且脚本为  <a href="vim9.html#Vim9">Vim9</a>  脚本，此错误也可能由函数未能导出引起。

                                                                <b class="vimtag"> <a name="E132">E132</a> </b>
用户函数的递归调用受到  <a href="options.html#'maxfuncdepth'">'maxfuncdepth'</a>  选项的限制。

也可以使用  <a href="eval.html#:eval">:eval</a> 。不支持范围，但支持方法的链式调用，例如: 
<code class="example">        eval GetList()-&gt;Filter()-&gt;append('$')</code>
<code class="example"></code>
函数也可以在表达式计算的一部分或作为方法调用: 
<code class="example">        let x = GetList()</code>
<code class="example">        let y = GetList()-&gt;Filter()</code>
<code class="example"></code>
</section><hr class="doubleline" /><section class=inner>
<h4></h4><code class="section">3. 函数清理 </code>
                                                        <b class="vimtag"> <a name=":defer">:defer</a> </b>
:defer <code class="special">{func}</code>(<code class="special">{args}</code>)   当前函数结束时调用 <code class="special">{func}</code>。<code class="special">{args}</code> 的计算在这里进行。

一个常见的情况是函数内某个命令有全局效果，而函数结束时应撤销其效果。要在各种环
境下处理好这种情况是很不容易的。尤其是出现了突发情况的时候。用 try/finally 块
可以对付，但如果有多次类似的情形，处理就显得很复杂。

一个更简便的方法是  <code class="badlink">defer</code> 。它调度函数返回时，执行函数调用，不管是否有出错情
形。例如: 
<code class="example">        func Filter(text) abort</code>
<code class="example">          call writefile(a:text, 'Tempfile')</code>
<code class="example">          call system('filter &lt; Tempfile &gt; Outfile')</code>
<code class="example">          call Handle('Outfile')</code>
<code class="example">          call delete('Tempfile')</code>
<code class="example">          call delete('Outfile')</code>
<code class="example">        endfunc</code>
<code class="example"></code>
这里，如果有某些情况使函数中途中止，'Tempfile' 和 'Outfile' 不会被删除。
 <a href="userfunc.html#:defer">:defer</a>  可用于避免之: 
<code class="example">        func Filter(text) abort</code>
<code class="example">          call writefile(a:text, 'Tempfile')</code>
<code class="example">          defer delete('Tempfile')</code>
<code class="example">          defer delete('Outfile')</code>
<code class="example">          call system('filter &lt; Tempfile &gt; Outfile')</code>
<code class="example">          call Handle('Outfile')</code>
<code class="example">        endfunc</code>
<code class="example"></code>
<code class="note">注意</code> 删除 "Outfile" 的调度发生在  <a href="builtin.html#system()">system()</a>  之前，因为  <a href="builtin.html#system()">system()</a>  失败时此文件
可能已经创建。

延迟函数以相反顺序调用，最后加入的最先执行。一个无用的例子: 
<code class="example">        func Useless() abort</code>
<code class="example">          for s in range(3)</code>
<code class="example">            defer execute('echomsg "number ' .. s .. '"')</code>
<code class="example">          endfor</code>
<code class="example">        endfunc</code>
<code class="example"></code>
现在  <a href="message.html#:messages">:messages</a>  会显示:
        number 2
        number 1
        number 0

丢弃延迟函数的任何返回值。函数后面不能跟其它部分，如 "-&gt;func" 和 ".member"。目
前不支持 `:defer GetArg()-&gt;TheFunc()`，但将来可能会。

延迟函数的执行过程中，有错误会报告但不中止执行。

不接受范围。函数可以是带额外参数的偏函数，但不支持字典函数。 <b class="vimtag"> <a name="E1300">E1300</a> </b>

</section><hr class="doubleline" /><section class=inner>
<h4></h4>4. 自动载入函数
                                                        <b class="vimtag"> <a name="autoload-functions">autoload-functions</a> </b>
如果使用很多或者很大的函数，可以在需要使用它们的时候才自动提供其定义。有两个方
法: 用自动命令，还有用 <a href="options.html#'runtimepath'">'runtimepath'</a> 里的 "autoload" 目录。

 <a href="vim9.html#Vim9">Vim9</a>  脚本也有导入脚本的自动载入机制，见  <a href="vim9.html#import-autoload">import-autoload</a> 。


<code class="section">使用自动命令 </code>

用户手册  <code class="badlink">41.14</code>  一节有介绍。

自动命令可用于很长的 Vim 脚本的插件。你可以定义自动命令然后用  <a href="repeat.html#:finish">:finish</a>  快速退
出脚本。这使得 Vim 启动快得多。这时，自动命令应该再次载入相同的文件，并设置变
量使得  <a href="repeat.html#:finish">:finish</a>  命令被跳过。

使用 FuncUndefined 自动命令事件，它需要一个能匹配等待定义的函数的模式。例如: 
<code class="example"></code>
<code class="example">        :au FuncUndefined BufNet* source ~/vim/bufnetfuncs.vim</code>
<code class="example"></code>
文件 "~/vim/bufnetfuncs.vim" 这时应该定义 "BufNet" 开始的函数。另见
 <a href="autocmd.html#FuncUndefined">FuncUndefined</a> 。


<code class="section">使用 autoload 脚本 </code>
                                                        <b class="vimtag"> <a name="autoload">autoload</a> </b> <b class="vimtag"> <a name="E746">E746</a> </b>
用户手册  <a href="usr_52.html#52.2">52.2</a>  一节有介绍。

在 "autoload" 目录里定义脚本更简单，但需要使用准确的文件名。能够自动载入的函数
的名字形如: 
<code class="example"></code>
<code class="example">        :call filename#funcname()</code>
<code class="example"></code>
这些函数总是全局的，在 Vim9 脚本中要用 "g:": 
<code class="example">        :call g:filename#funcname()</code>
<code class="example"></code>
这样的函数如果调用时还没有定义，Vim 在 <a href="options.html#'runtimepath'">'runtimepath'</a> 里的 "autoload" 目录搜索
脚本文件 "filename.vim"。例如 "~/.vim/autoload/filename.vim"。该文件这时应该这
样定义函数: 
<code class="example"></code>
<code class="example">        function filename#funcname()</code>
<code class="example">           echo "Done!"</code>
<code class="example">        endfunction</code>
<code class="example"></code>
如果文件不存在，Vim 也会在 <a href="options.html#'packpath'">'packpath'</a> (在 "start" 之下) 里搜索文件，以便在
.vimrc 里，这些包还没加到 <a href="options.html#'runtimepath'">'runtimepath'</a> 前 (见  <a href="repeat.html#packages">packages</a> )，就可以调用包里的函
数。

文件名和函数的 # 之前的名字必须完全匹配，而定义的函数名也必须和调用时使用的形
式完全一致。在 Vim9 脚本中必须要用 "g:" 前缀: 
<code class="example">        function g:filename#funcname()</code>
<code class="example"></code>
或对已编译函数而言: 
<code class="example">        def g:filename#funcname()</code>
<code class="example"></code>
可以使用子目录。函数名每个 # 相当于路径分隔符。这样，调用函数: 
<code class="example"></code>
<code class="example">        :call foo#bar#func()</code>
<code class="example"></code>
的时候，Vim 寻找 <a href="options.html#'runtimepath'">'runtimepath'</a> 里的文件 "autoload/foo/bar.vim"。

也适用于读取还没有设置的变量: 
<code class="example"></code>
<code class="example">        :let l = foo#bar#lvar</code>
<code class="example"></code>
不过，如果 autoload 脚本已经载入，不会为未知的变量再次载入该脚本。

给这样的变量赋值并没有什么特别。这可以用于在载入 autoload 脚本之前给它传递一些
设置: 
<code class="example"></code>
<code class="example">        :let foo#bar#toggle = 1</code>
<code class="example">        :call foo#bar#func()</code>

<code class="note">注意</code> 如果你不小心调用了应该在 autoload 脚本里定义，但该脚本实际没有定义的函数
时，会得到函数消失的错误信息。修正 autoload 脚本后它不会自动重新载入。需要重启
Vim 或手动载入该脚本。

还有，<code class="note">注意</code> 如果你有两个脚本文件，不能在使用的函数定义之前同时从一个文件里调用
另一个文件里的函数并且从那个文件里调用这个文件的函数。
避免在顶层使用自动载入功能。

 <a href="vim9.html#Vim9">Vim9</a>  脚本里如果定义函数用的名字里有 "#" 字符，会报错 <b class="vimtag"> <a name="E1263">E1263</a> </b> 。必须用不带
"#" 的名字使使用  <a href="vim9.html#:export">:export</a> 。

提示: 如果你发布很多脚本，可以用  <a href="pi_vimball.html#vimball">vimball</a>  工具把它们捆绑在一起。另请阅读用户
手册  <a href="usr_51.html#distribute-script">distribute-script</a> 。


 vim:tw=78:ts=8:noet:ft=help:norl:
</section>
</article>
<footer>
Generated by vim2html
</footer>
</body>
</html>
